#pragma once

#include <iostream>

#define CLO_RESET   "\e[0m"

#define TEXT_BLACK  "\e[0;30m"
#define TEXT_RED    "\e[0;31m"
#define TEXT_GREEN  "\e[0;32m"
#define TEXT_YELLOW "\e[0;33m"
#define TEXT_BLUE   "\e[0;34m"
#define TEXT_PURPLE "\e[0;35m"
#define TEXT_CYAN   "\e[0;36m"
#define TEXT_WHITE  "\e[0;37m"

#define BKG_BLACK   "\e[40m"
#define BKG_RED     "\e[41m"
#define BKG_GREEN   "\e[42m"
#define BKG_YELLOW  "\e[43m"
#define BKG_BLUE    "\e[44m"
#define BKG_PURPLE  "\e[45m"
#define BKG_CYAN    "\e[46m"
#define BKG_WHITE   "\e[47m"

#define GET_KEY(map) map.first
#define GET_VAL(map) map.second

#define PrintErr(...) \
  printf(TEXT_RED); \
  printf(__VA_ARGS__); \
  printf(CLO_RESET);

#define Panic(...) \
  printf(TEXT_RED); \
  printf("%s:%d:%s\n", __FILE__, __LINE__, __func__); \
  printf(__VA_ARGS__); \
  printf(CLO_RESET); \
  printf("\n"); \
  exit(-1);

#define Log(...) \
  printf(TEXT_BLUE); \
  printf("%s:%d:%s:", __FILE__, __LINE__, __func__); \
  printf(__VA_ARGS__); \
  printf(CLO_RESET); \
  printf("\n");

#ifdef DEBUG
#define Assert(decl, ...) \
  if(!(decl)) { \
    printf(TEXT_RED); \
    printf(__VA_ARGS__); \
    printf(CLO_RESET); \
    printf("\n"); \
    assert(decl); \
  }
#else
#define Assert(decl, ...)
#endif

#define VISIT(VISITOR, class) \
  void class::accept(VISITOR & visitor) { \
    visitor.visit(*this); \
  }
